﻿/*-------------------------------------------------------------------------
 * 版权所有：	黑客马拉松
 * 作者：		罗毅
 * 联系方式：	whluoyi@gmail.com
 * 创建时间：	2016/10/29 11:23:16
 * 版本号：		v1.0
 * 用途描述：	日志代理
 *  -------------------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;

namespace SuperMarieApi.Log.LogAgent.Xml
{
    /// <summary>
    /// Xml读取操作类
    /// </summary>
    internal class XHelper
    {
        #region XRead
        /// <summary>
        /// 读取生成Xml映射
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public XRow[] XRead(XReader reader)
        {
            XRow[] xRows = new XRead().Read(reader);
            return xRows;
        }
        /// <summary>
        /// 读取生成Xml树
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public XNode XReadTree(XReader reader)
        {
            XNode result = new XRead().ReadTree(reader);
            return result;
        }
        #endregion

        #region TRead
        /// <summary>
        /// 是否为基本类型或字符串
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool typeIsPrimitive<T>()
        {
            Type type = typeof(T);
            return type.IsPrimitive || type == typeof(String);
        }
        /// <summary>
        /// 数据类型转化
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private object changeType(object value, Type type)
        {
            if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
            if (value == null) return null;
            if (type == value.GetType()) return value;
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value as string);
                else
                    return Enum.ToObject(type, Convert.ToInt32(value));
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = changeType(value, innerType);
                return Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid)) return new Guid(value as string);
            if (value is string && type == typeof(Version)) return new Version(value as string);
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }
        /// <summary>
        /// 构造类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private T createInstance<T>()
        {
            Type type = typeof(T);
            T result = default(T);
            if (!typeIsPrimitive<T>())
            {
                result = (T)type.Assembly.CreateInstance(type.FullName);
                return result;
            }
            return default(T);
        }
        /// <summary>
        /// 获取默认值
        /// </summary>
        /// <param name="xRow"></param>
        /// <returns></returns>
        private object getDefaultValue(XRow xRow)
        {
            if (xRow.KeyValue.Count == 0)
            {
                return null;
            }
            if (xRow.KeyValue.ContainsKey(XRow.XML_CDATA_NAME))
            {
                return xRow.KeyValue[XRow.XML_CDATA_NAME];
            }
            return xRow.KeyValue[0];
        }
        /// <summary>
        /// 通过Key获取值
        /// </summary>
        /// <param name="xRow"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private object getValue(XRow xRow, string key)
        {
            if (xRow.KeyValue.Count == 0)
            {
                return null;
            }
            if (xRow.KeyValue.ContainsKey(key))
            {
                return xRow.KeyValue[key];
            }
            if (xRow.Name.Equals("add",StringComparison.CurrentCultureIgnoreCase)
                && xRow.KeyValue.ContainsKey("key")
                && xRow.KeyValue["key"] != null
                && xRow.KeyValue["key"].ToString().Equals(key, StringComparison.CurrentCultureIgnoreCase)
                && xRow.KeyValue.ContainsKey("value"))
            {
                return xRow.KeyValue["value"];
            }
            return null;
        }
        /// <summary>
        /// 映射类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xRow"></param>
        /// <returns></returns>
        private T mapperClass<T>(XRow xRow)
        {
            var result = createInstance<T>();
            Type type = typeof(T);
            foreach (PropertyInfo pi in type.GetProperties())
            {
                var value = getValue(xRow, pi.Name);
                value = changeType(value, pi.PropertyType);
                if (value != null)
                {
                    pi.SetValue(result, value, null);
                }
            }
            return result;
        }
        /// <summary>
        /// 读取生成映射类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xRow"></param>
        /// <returns></returns>
        public XTarget<T> TRead<T>(XRow xRow)
        {
            var result = default(T);
            Type type = typeof(T);
            if (type == typeof(string))
            {
                result = (T)getDefaultValue(xRow);
                if (result == null)
                {
                    result = (T)((object)string.Empty);
                }
            }
            else if (type.IsPrimitive)
            {
                result = (T)changeType(getDefaultValue(xRow), type);
            }
            else
            {
                result = mapperClass<T>(xRow);
            }
            return new XTarget<T>() { Instance = result, XRow = xRow };
        }
        /// <summary>
        /// 读取生成映射类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader"></param>
        /// <returns></returns>
        public XTarget<T>[] TRead<T>(XReader reader)
        {
            var xRows = new XRead().Read(reader);
            var lst = new List<XTarget<T>>();
            foreach (var xRow in xRows)
            {
                var t = TRead<T>(xRow);
                if (t != null)
                {
                    lst.Add(t);
                }
            }
            return lst.ToArray();
        }
        #endregion

        #region TMapper
        /// <summary>
        /// 读取生成映射类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xRow"></param>
        /// <returns></returns>
        public T TMapper<T>(XRow xRow)
        {
            var target = TRead<T>(xRow);
            return target.Instance;
        }
        /// <summary>
        /// 读取生成映射类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader"></param>
        /// <returns></returns>
        public T[] TMapper<T>(XReader reader)
        {
            var targets = TRead<T>(reader);
            List<T> result = new List<T>();
            foreach (var target in targets)
            {
                var t = target.Instance;
                if (t != null)
                {
                    result.Add(t);
                }
            }
            return result.ToArray();
        }
        #endregion

    }
}
